import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:kq_flutter_core_widget/utils/kq_screen_util.dart';
import '../../resources/kq_theme_colors.dart';

import '../tip/kq_tip.dart';
import 'kq_rainbow_tips_builder.dart';
import 'kq_rainbow_value.dart';

/// 彩虹条
/// 要实现点击组件外区域关闭，就必须在最外层包一个GestureDetector，并用globeKey在onTap中实现close方法
class KqRainbowBar extends StatefulWidget {
  const KqRainbowBar({
    Key? key,
    this.height,
    this.width,
    this.data,
    this.rainbowBarClickListener,
    this.rainbowBarMoveListener,
    this.tipsBuilder,
    this.customTipsPainter,
    this.showTips = false,
  }) : super(key: key);

  /// 高度，如果外部容器有高度，可以不传
  final double? height;

  /// 宽度，如果外部容器有宽度，可以不传
  final double? width;

  /// 是否显示气泡
  final bool? showTips;

  final List<KqRainbowValue>? data;

  /// 彩虹条的按下回调
  final OnKqRainbowBarClickListener? rainbowBarClickListener;

  /// 彩虹条的移动回调
  final OnKqRainbowBarMoveListener? rainbowBarMoveListener;

  /// tips的构造器
  final KqRbTipsBuilder? tipsBuilder;

  /// 如果构造器无法实现，则传入自定义的CustomPainter来绘制tips
  final CustomPainter? customTipsPainter;

  @override
  State<StatefulWidget> createState() {
    return KqRainbowBarState();
  }
}

class KqRainbowBarState extends State<KqRainbowBar> {
  /// 要存的每项开头坐标
  List<double> startPositions = [];

  /// 要存的每项中间坐标
  List<double> centerPositions = [];

  /// 要存的每项结束坐标
  List<double> endPositions = [];

  List<Size> boxSizes = [];

  /// 点击item的中心坐标(组件内)
  double? centerPosition;

  /// 组件内坐标与全局坐标的水平距离
  double? globalLocalDx;

  /// 文案
  String text = "";

  /// 当前项
  int? position;

  /// 跟随标志
  final LayerLink layerLink = LayerLink();

  /// 悬浮框
  OverlayEntry? overlayEntry;

  /// 是否正在显示
  bool isShowing = false;

  Timer? timer;

  /// 显示tip
  void show(EasyTipBox easyTipBox) {
    if (!(widget.showTips ?? false)) {
      return;
    }

    closeTips();

    overlayEntry = _createOverlayEntry(easyTipBox);
    Overlay.of(context)?.insert(overlayEntry!);
    isShowing = true;
    timer?.cancel();
    if (widget.tipsBuilder?.autoClose ?? true) {
      timer = Timer(
          widget.tipsBuilder?.aliveTime ?? const Duration(milliseconds: 3000),
          () {
        closeTips();
      });
    }
  }

  /// 主动关闭tip,用globeKey调用,要在最外层包个点击事件
  void closeTips() {
    if (isShowing == true) {
      overlayEntry?.remove();
      timer?.cancel();
      isShowing = false;
      position = null;
    }
  }

  void checkPositionForPanDown(DragDownDetails details) {
    //获取当前触摸点的局部坐标
    Offset localPosition = details.localPosition;
    //获取当前触摸点的全局坐标
    Offset globalPosition = details.globalPosition;
    for (int i = 0; i < centerPositions.length; i++) {
      if (localPosition.dx < endPositions.elementAt(i) &&
          localPosition.dx > startPositions.elementAt(i)) {
        globalLocalDx = globalPosition.dx - localPosition.dx;
        centerPosition = centerPositions.elementAt(i);
        text = widget.data!.elementAt(i).text;
        if (i != position) {
          position = i;
          show(EasyTipBox(boxSizes.elementAt(i), globalLocalDx!));
        }
        if (widget.rainbowBarClickListener != null) {
          widget.rainbowBarClickListener!(
              i,
              Offset(centerPosition!, 0),
              Offset(centerPosition! + globalLocalDx!,
                  globalPosition.dy - localPosition.dy),
              widget.data!.elementAt(i));
        }
      }
    }
  }

  void checkPositionForMove(DragUpdateDetails details) {
    //获取当前触摸点的局部坐标
    Offset localPosition = details.localPosition;
    //获取当前触摸点的全局坐标
    Offset globalPosition = details.globalPosition;
    for (int i = 0; i < centerPositions.length; i++) {
      if (localPosition.dx < endPositions.elementAt(i) &&
          localPosition.dx > startPositions.elementAt(i)) {
        globalLocalDx = globalPosition.dx - localPosition.dx;
        centerPosition = centerPositions.elementAt(i);
        text = widget.data!.elementAt(i).text;
        if (i != position) {
          position = i;
          show(EasyTipBox(boxSizes.elementAt(i), globalLocalDx!));
        }
        if (widget.rainbowBarMoveListener != null) {
          widget.rainbowBarMoveListener!(
              i,
              Offset(centerPosition!, 0),
              Offset(centerPosition! + globalLocalDx!,
                  globalPosition.dy - localPosition.dy),
              widget.data!.elementAt(i));
        }
      }
    }
  }

  /// 生成悬浮窗
  OverlayEntry _createOverlayEntry(EasyTipBox easyTipBox) => OverlayEntry(
        builder: (BuildContext context) => UnconstrainedBox(
          // 跟随者
          child: CompositedTransformFollower(
            link: layerLink,
            showWhenUnlinked: false,
            child: RepaintBoundary(
              child: CustomPaint(
                foregroundPainter: TipsPainter(
                    easyTipBox: easyTipBox,
                    text: text,
                    tipDirection:
                        widget.tipsBuilder?.tipDirection ?? TipDirection.top,
                    windowPadding: widget.tipsBuilder?.windowPadding ??
                        EdgeInsets.symmetric(vertical: 22.r, horizontal: 24.r),
                    arrowWidth: widget.tipsBuilder?.arrowWidth ?? 24.r,
                    arrowHeight: widget.tipsBuilder?.arrowHeight ?? 15.r,
                    backgroundColor: widget.tipsBuilder?.backgroundColor ??
                        KqThemeColors.textBlack65,
                    textColor:
                        widget.tipsBuilder?.textColor ?? KqThemeColors.bgWhite,
                    fontSize: widget.tipsBuilder?.fontSize ?? 24.sp,
                    radius: widget.tipsBuilder?.radius ?? Radius.circular(4.r),
                    tipsOffset: widget.tipsBuilder?.tipsOffset ?? 4.r,
                    tipsTextAlign:
                        widget.tipsBuilder?.tipsTextAlign ?? TextAlign.center),
              ),
            ),
          ),
        ),
      );

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onPanDown: (details) {
        checkPositionForPanDown(details);
      },
      onHorizontalDragUpdate: (dragUpdateDetails) {
        checkPositionForMove(dragUpdateDetails);
      },
      onTap: (widget.showTips ?? false)
          ? () {
              /// 这里写一个空的onTap的目的是，与外层的onTap竞争，并胜出，来达到在该组件上点击时，不触发外层onTap的目的
            }
          : null,
      // 被跟随者
      child: CompositedTransformTarget(
        link: layerLink,
        child: SizedBox(
          width: widget.width ?? double.infinity,
          height: widget.height ?? double.infinity,
          child: RepaintBoundary(
            child: CustomPaint(
              painter: ItemPainter(
                data: widget.data,
                rainbowBarEndDrawListener:
                    (startPositions, centerPositions, endPositions, boxSizes) {
                  this.startPositions = startPositions;
                  this.centerPositions = centerPositions;
                  this.endPositions = endPositions;
                  this.boxSizes = boxSizes;
                },
              ),
            ),
          ),
        ),
      ),
    );
  }
}

/// 彩虹条的点击返回
typedef OnKqRainbowBarClickListener = void Function(
    int position,

    /// 选中item的中间位置的控件内坐标
    Offset dialogShowPositionLocal,

    /// 选中item的中间位置的屏幕内坐标
    Offset dialogShowPositionGlobal,
    KqRainbowValue value);

/// 彩虹条的移动返回
typedef OnKqRainbowBarMoveListener = void Function(
    int position,

    /// 选中item的中间位置的控件内坐标
    Offset dialogShowPositionLocal,

    /// 选中item的中间位置的屏幕内坐标
    Offset dialogShowPositionGlobal,
    KqRainbowValue value);

/// 彩虹条的绘制结束返回绘制坐标
typedef OnKqRainbowBarEndDrawListener = void Function(
    List<double> startPositions,
    List<double> centerPositions,
    List<double> endPositions,
    List<Size> boxSizes);

class ItemPainter extends CustomPainter {
  ItemPainter({Key? key, this.data, this.rainbowBarEndDrawListener});

  final Paint _paint = Paint()..style = PaintingStyle.fill;

  final List<KqRainbowValue>? data;

  final OnKqRainbowBarEndDrawListener? rainbowBarEndDrawListener;

  List<double> startPositions = [];
  List<double> centerPositions = [];
  List<double> endPositions = [];
  List<Size> boxSizes = [];

  @override
  void paint(Canvas canvas, Size size) {
    startPositions = [];
    centerPositions = [];
    endPositions = [];
    if (data == null) {
      return;
    }
    double totalWidth = 0;
    for (KqRainbowValue item in data!) {
      totalWidth = totalWidth + item.value;
    }
    double simpleWidth = size.width / totalWidth;
    double countWidth = 0;
    for (int i = 0; i < data!.length; i++) {
      KqRainbowValue value = data!.elementAt(i);
      _paint.color = value.color;

      /// 获取左上角和右下角的坐标
      Offset startLeftTop = Offset(countWidth, 0);
      Offset endRightBottom =
          Offset(countWidth + simpleWidth * value.value, size.height);
      canvas.drawRect(Rect.fromPoints(startLeftTop, endRightBottom), _paint);
      final double oldWidth = countWidth;
      startPositions.add(oldWidth);
      countWidth = countWidth + simpleWidth * value.value;
      double centerPosition = countWidth - (countWidth - oldWidth) / 2;
      centerPositions.add(centerPosition);
      endPositions.add(countWidth);
      // 这个size是特殊的，本质上是为了兼容TipsPainter而单独构造的
      boxSizes.add(Size(centerPosition * 2, size.height));
    }
    if (rainbowBarEndDrawListener != null) {
      rainbowBarEndDrawListener!(
          startPositions, centerPositions, endPositions, boxSizes);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}
